View Javadoc
1 /* 2 * Title: S/MIME Project 3 * Description: S/MIME email sending capabilities 4 * @Author Vladimir Radisic 5 * @Version 2.0.1 6 */ 7 8 package org.webdocwf.util.smime.util; 9 10 11 import java.security.KeyStore; 12 import java.security.Signature; 13 import java.security.PrivateKey; 14 import java.security.cert.X509Certificate; 15 import java.util.Vector; 16 import java.util.Enumeration; 17 import org.webdocwf.util.smime.exception.SMIMEException; 18 import org.webdocwf.util.smime.exception.ErrorStorage; 19 import org.bouncycastle.jce.provider.JDKDigestSignature; 20 21 import java.security.cert.Certificate; 22 23 24 /*** 25 * PFXUtils class has static methods which are dealing with .pfx, or .p12 26 * files. The file (of this types) presents storage for keeping certificate 27 * chain and private key. Information from this files are being transported 28 * through programs via instance of the Java class KeyStore. 29 */ 30 public class PFXUtils { 31 32 /*** 33 * Returns the owner's Certificate from his .pfx or .p12 file (KeyStore) 34 * @param ks0 container for information from .pfx or .p12 file 35 * @return Owner's Certificate 36 * @exception SMIMEException if problem with extracting certificate 37 * chain from .pfx or .p12 file or with aliases in pfx or p12 file arrises. 38 * Also, it can be caused by non SMIMEException which is KeyStoreException. 39 */ 40 public static X509Certificate getPFXOwnerX509Certificate(KeyStore ks0) throws SMIMEException { 41 X509Certificate[] certChain = PFXUtils.getCertificateChain(ks0); 42 43 if (certChain != null) 44 return certChain[0]; 45 46 return PFXUtils.getAllX509Certificate(ks0)[0]; 47 } 48 49 /*** 50 * Returns the Private key of the certificate's owner from .pfx or .p12 51 * file (pkcs12 format) 52 * @param ks0 container for information from .pfx or .p12 file 53 * @return Owners private key 54 * @exception SMIMEException caused by non SMIMEException which can be one of 55 * the following: KeyStoreException, UnrecoverableKeyException or 56 * NoSuchAlgorithmException. 57 */ 58 public static PrivateKey getPrivateKey(KeyStore ks0) throws SMIMEException { 59 String keyAlias = null; // Alias for public key certificate corresponding to private key 60 PrivateKey returnPrivateKey = null; 61 62 try { 63 Enumeration en = ks0.aliases(); 64 65 while (en.hasMoreElements()) { 66 String temp = (String) en.nextElement(); 67 68 if (ks0.isKeyEntry(temp)) 69 keyAlias = temp; 70 } 71 returnPrivateKey = (PrivateKey) ks0.getKey(keyAlias, null); // Obtaining private key as PrivateKey class 72 } catch (Exception e) { 73 throw SMIMEException.getInstance("org.webdocwf.util.smime.util.PFXUtils", 74 e, "getPrivateKey"); 75 } 76 return returnPrivateKey; 77 } 78 79 /*** 80 * Returns all X509 Certificates stored in .pfx, or .p12 files 81 * (KeyStore). This method performs same task as method getCertificateChain() but 82 * on less elegant way. In the future project version, it will be completely 83 * replaced with the getCertificateChain() method. 84 * @param ks0 container for information from .pfx or .p12 file 85 * @return Certificate chain represented as array of X509Certificate objects 86 * with the owner's certificate at the first place. 87 * @exception SMIMEException if problem with extracting certificate 88 * chain from .pfx or .p12 file or with aliases in pfx or p12 file arrises. 89 * Also, it can be caused by non SMIMEException which is KeyStoreException. 90 */ 91 public static X509Certificate[] getAllX509Certificate(KeyStore ks0) throws SMIMEException { 92 93 Vector v = new Vector(0, 1); // Collection of certificates from pfx file 94 String certAlias = null; // Alias for public key certificate corresponding to certificate 95 X509Certificate keyEntryCert = null; 96 int numberOfAlias = 0; 97 int numberOfCert = 0; 98 int numberOfKeyEntry = 0; 99 100 try { 101 Enumeration en = ks0.aliases(); 102 103 while (en.hasMoreElements()) { 104 String temp = (String) en.nextElement(); 105 106 numberOfAlias++; 107 if (ks0.isKeyEntry(temp)) { // owner 108 numberOfKeyEntry++; 109 keyEntryCert = (X509Certificate) ks0.getCertificate(temp); 110 } 111 if (ks0.isCertificateEntry(temp)) { 112 X509Certificate cerCert; 113 114 cerCert = (X509Certificate) ks0.getCertificate(temp); // Getting certificate 115 v.add(cerCert); 116 numberOfCert++; 117 } 118 } 119 if ((numberOfAlias == numberOfCert + numberOfKeyEntry) & (numberOfKeyEntry == 1)) { 120 if (keyEntryCert != null) { 121 v.add(0, keyEntryCert); // is owners certificate is asociated with "key entry" alias 122 } 123 } else 124 throw new SMIMEException("org.webdocwf.util.smime.util.PFXUtils", 1037); 125 } catch (Exception e) { 126 throw SMIMEException.getInstance("org.webdocwf.util.smime.util.PFXUtils", 127 e, "getAllX509Certificate"); 128 } 129 if (v.size() != 1) 130 v = getOwnersCertOnTop(v); 131 X509Certificate[] certChain = new X509Certificate[v.size()]; 132 133 for (int i = 0; i != v.size(); i++) 134 certChain[i] = (X509Certificate) v.elementAt(i); 135 return certChain; 136 } 137 138 /*** 139 * Returns all X509 Certificates stored in .pfx, or .p12 files (KeyStore). This 140 * method performs same task as method getAllX509Certificate() but on more elegant 141 * way. 142 * @param ks0 container for information from .pfx or .p12 file 143 * @return Certificate chain represented as array of X509Certificate objects 144 * with the owner's certificate at the first place. 145 * @exception SMIMEException caused by non SMIMEException which is 146 * KeyStoreException. 147 */ 148 public static X509Certificate[] getCertificateChain(KeyStore ks0) throws SMIMEException { 149 150 boolean errorInChainReading = true; 151 int numberOfCert = 0; 152 Certificate[] certChain = new Certificate[0]; 153 154 try { 155 Enumeration en = ks0.aliases(); 156 157 while (en.hasMoreElements()) { 158 try { 159 String tempAlias = (String) en.nextElement(); 160 Certificate[] tempCertChain = (Certificate[]) ks0.getCertificateChain(tempAlias); 161 162 if (tempCertChain != null && tempCertChain.length == certChain.length) { 163 errorInChainReading = true; 164 } 165 if (tempCertChain != null && tempCertChain.length > certChain.length) { 166 errorInChainReading = false; 167 certChain = tempCertChain; 168 } 169 if (ks0.isCertificateEntry(tempAlias)) 170 numberOfCert++; 171 } catch (Exception e) { 172 continue; 173 } 174 } 175 } catch (Exception e) { 176 throw SMIMEException.getInstance("org.webdocwf.util.smime.util.PFXUtils", 177 e, "getCertificateChain"); 178 } 179 180 if (certChain == null || certChain.length == 0 || errorInChainReading || 181 certChain.length != numberOfCert) 182 return null; 183 else { 184 X509Certificate[] returnCertChain = new X509Certificate[certChain.length]; 185 186 for (int i = 0; i != certChain.length; i++) { 187 returnCertChain[i] = (X509Certificate) certChain[i]; 188 } 189 return returnCertChain; 190 } 191 192 } 193 194 /*** 195 * Orders certificates in certificate chain with owner's certificate at the 196 * first position, in Vector representation, and root CA at the last position. 197 * @param v0 all certificates from .pfx or .p12 file 198 * @return Ordered certificates in Vector. Starts from owner's certificate (at 199 * first position) and ends with root CA certificate (at last position). 200 * @exception SMIMEException if problem with extracting certificate 201 * chain from .pfx or .p12 file arrises. 202 */ 203 private static Vector getOwnersCertOnTop(Vector v0) throws SMIMEException { 204 Vector inOrder = new Vector(0, 1); // Storage for certificate chain 205 boolean ver = false; 206 int j = 0; 207 208 while (inOrder.size() == 0) { 209 if (j == v0.size()) 210 throw new SMIMEException("org.webdocwf.util.smime.util.PFXUtils", 1038); 211 for (int i = 0; i != v0.size(); i++) { 212 if (i != j) { 213 ver = verification((X509Certificate) v0.elementAt(j), (X509Certificate) v0.elementAt(i)); 214 if (ver) { 215 inOrder.add(v0.elementAt(j)); 216 inOrder.add(v0.elementAt(i)); 217 if (i > j) { 218 v0.removeElementAt(i); 219 v0.removeElementAt(j); 220 } else { 221 v0.removeElementAt(j); 222 v0.removeElementAt(i); 223 } 224 break; 225 } 226 } 227 } 228 if (ver) 229 break; 230 j++; 231 } 232 j = 0; 233 int lenBefore = v0.size(); 234 235 while (v0.size() != 0) { 236 if (j > lenBefore) 237 throw new SMIMEException("org.webdocwf.util.smime.util.PFXUtils", 1038); 238 for (int i = 0; i != v0.size(); i++) { 239 ver = verification((X509Certificate) v0.elementAt(i), (X509Certificate) inOrder.firstElement()); 240 if (ver) { 241 inOrder.add(0, v0.elementAt(i)); 242 v0.removeElementAt(i); 243 break; 244 } 245 ver = verification((X509Certificate) inOrder.lastElement(), (X509Certificate) v0.elementAt(i)); 246 if (ver) { 247 inOrder.add(v0.elementAt(i)); 248 v0.removeElementAt(i); 249 break; 250 } 251 } 252 j++; 253 } 254 return inOrder; 255 } 256 257 /*** 258 * Checks the relations between two certificates: if one of them is signer 259 * of another one. 260 * @param cerOwner certificate for check 261 * @param cerIssuer certificate for check 262 * @return true or false information about signing informatin between certificates 263 */ 264 private static boolean verification(X509Certificate cerOwner, X509Certificate cerIssuer) { 265 boolean ret = false; 266 267 try { 268 if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.113549.1.1.5")) { 269 JDKDigestSignature.SHA1WithRSAEncryption jd = new JDKDigestSignature.SHA1WithRSAEncryption(); 270 271 jd.initVerify(cerIssuer.getPublicKey()); 272 jd.update(cerOwner.getTBSCertificate()); 273 ret = jd.verify(cerOwner.getSignature()); 274 } else if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.10040.4.3")) { 275 Signature sig = Signature.getInstance("SHA1withDSA", "SUN"); 276 277 sig.initVerify(cerIssuer.getPublicKey()); 278 sig.update(cerOwner.getTBSCertificate()); 279 ret = sig.verify(cerOwner.getSignature()); 280 } else if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.113549.1.1.2")) { 281 JDKDigestSignature.MD2WithRSAEncryption jd = new JDKDigestSignature.MD2WithRSAEncryption(); 282 283 jd.initVerify(cerIssuer.getPublicKey()); 284 jd.update(cerOwner.getTBSCertificate()); 285 ret = jd.verify(cerOwner.getSignature()); 286 } else if (cerOwner.getSigAlgOID().equalsIgnoreCase("1.2.840.113549.1.1.4")) { 287 JDKDigestSignature.MD5WithRSAEncryption jd = new JDKDigestSignature.MD5WithRSAEncryption(); 288 289 jd.initVerify(cerIssuer.getPublicKey()); 290 jd.update(cerOwner.getTBSCertificate()); 291 ret = jd.verify(cerOwner.getSignature()); 292 } 293 } catch (Exception e) { 294 ret = false; 295 } 296 return ret; 297 } 298 299 } 300

This page was automatically generated by Maven